import React, {Component} from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import TextBlock from '../components/TextBlock';
import TreeBlock from '../components/TreeBlock';
import ErrorBlock from '../components/ErrorBlock';
import CoderSelector from '../components/CoderSelector';
import {createTextCoders, createDataCoders} from '../formats/factory';

export default class BlockChain extends Component {
  static propTypes = {
    blocks: PropTypes.array,
    coders: PropTypes.array,
  }

  state = {
    blocks: this.props.blocks || [''],
    coders: this.props.coders || [],
  }

  blockChange = index => {
    return value => {
      this.state.blocks[index] = value;
      this.compute(index);
      this.forceUpdate();
    };
  }

  coderChange = index => {
    return coder => {
      this.state.coders[index] = coder;
      this.state.blocks.length = this.state.coders.length = index + 1;
      this.compute(index);
      this.forceUpdate();
    }
  }

  coderOptionChange = index => {
    return coder => {
      this.compute(index);
      this.forceUpdate();
    }
  }

  compute(index) {
    const coder = this.state.coders[index];
    if (coder) {
      try {
        this.state.blocks[index+1] = coder.compute(this.state.blocks[index]);
        this.compute(index+1);
      } catch (error) {
        this.state.blocks[index+1] = error;
      }
    }
  }

  renderBlock = (block, index) => {
    switch(index % 2) {
      case 0:
        return (
          <div key={index} className="block-container">
            <TextBlock text={block} onChange={this.blockChange(index)} />
            <CoderSelector coder={this.state.coders[index]} coders={createTextCoders()} onSelection={this.coderChange(index)} onOptionChange={this.coderOptionChange(index)} />
          </div>
        );
      case 1:
        if (block instanceof Error) {
          return <ErrorBlock key={index} error={block} />;
        } else {
          return (
            <div key={index} className="block-container">
              <TreeBlock data={block} />
              <CoderSelector coder={this.state.coders[index]} coders={createDataCoders()} onSelection={this.coderChange(index)} onOptionChange={this.coderOptionChange(index)} />
            </div>
          );
        }
      default:
        return null;
    }
  }

  render() {
    const {
      blocks,
      coders,
      ...other
    } = this.props;

    return <div {...other}>
    {
      this.state.blocks.map(this.renderBlock)
    }
    </div>;
  }
}
